package org.truenewx.tnxjee.webmvc.security.web.access;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
import org.truenewx.tnxjee.service.exception.ResolvableException;
import org.truenewx.tnxjee.webmvc.method.support.HandlerMethodMapping;
import org.truenewx.tnxjee.webmvc.response.exception.message.ResolvableExceptionMessageSaver;
import org.truenewx.tnxjee.webmvc.security.web.RestResponseResultDecider;

import java.io.IOException;

/**
 * 访问拒绝后的业务异常处理器
 */
public class AccessDeniedBusinessExceptionHandler extends AccessDeniedHandlerImpl {

    @Autowired
    private ResolvableExceptionMessageSaver resolvableExceptionMessageSaver;
    @Autowired
    private HandlerMethodMapping handlerMethodMapping;
    @Autowired(required = false)
    private RestResponseResultDecider restResponseResultDecider;

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
            AccessDeniedException accessDeniedException) throws IOException, ServletException {
        Throwable cause = accessDeniedException.getCause();
        if (cause instanceof ResolvableException) {
            this.resolvableExceptionMessageSaver.saveMessage(request, response, null, (ResolvableException) cause);
        }

        if (this.handlerMethodMapping.isRestRequest(request, null)) {
            int status = HttpServletResponse.SC_FORBIDDEN; // 拒绝访问后的状态码
            if (this.restResponseResultDecider != null && this.restResponseResultDecider.supports(request)) {
                request.setAttribute(RestResponseResultDecider.ATTR_DEFAULT_STATUS, status);
                status = this.restResponseResultDecider.getAccessDeniedStatus();
            }
            response.setStatus(status);
        } else {
            super.handle(request, response, accessDeniedException);
        }
    }

}
